from flask import Flask, request, render_template, jsonify
from pyecharts.render import make_snapshot
from pyecharts import options as opts
from pyecharts.charts import Line, Pie, Bar, Scatter, WordCloud
from pyecharts.globals import ThemeType
import pandas as pd
import numpy as np
from pyecharts.commons.utils import JsCode

# 读取数据
data = pd.read_csv("最终版.csv", encoding='gbk')


# 生成饼图的函数
def generate_pie_chart(year):
    data_year = data[data['年份'] == year]
    if data_year.empty:
        raise ValueError(f"数据中无 {year} 年的记录，请检查年份输入或数据文件")
    split_labels = data_year['类型'].str.split('、', expand=False)
    all_labels = split_labels.explode().value_counts().reset_index()
    all_labels.columns = ['类型', '出现次数']
    pie_data = list(zip(all_labels['类型'], all_labels['出现次数']))
    pie = (
        Pie(init_opts=opts.InitOpts(theme=ThemeType.DARK, width="600px",height="400px"))
        .add(
            "",
            pie_data,
            radius="80%",
            label_opts=opts.LabelOpts(is_show=False)
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title=f"{year}年电视剧类型分布"),
                                     #pos_left="center"
            legend_opts=opts.LegendOpts(
                is_show=True,
                pos_right="0.1%",
                orient="vertical",
                align="left",
                type_="scroll",
                item_width=10,
                item_height=10,
                textstyle_opts=opts.TextStyleOpts(font_size=10)
            ),
            tooltip_opts=opts.TooltipOpts(
                formatter="{b}: {d}%",
                trigger="item"
            )
        )
        .set_series_opts(
            itemstyle_opts=opts.ItemStyleOpts(
                border_width=1,
                border_color="#fff"
            )
        )
    )

    return pie

# 热度Top10水平条形图
def create_top10_hot_bar(year):
    data_year = data[data['年份'] == year]

    # 按热度降序排序
    top10_hot = data_year.sort_values('热度', ascending=False).head(10)

    # 反转数据，使热度最高的在最上方
    reversed_data = top10_hot.iloc[::-1].copy()

    # 创建条形图，修改宽度和高度
    bar = (
        Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK, width="800px", height="400px"))  # 修改这里的宽度和高度
        .add_xaxis(reversed_data['剧名'].tolist())
        .add_yaxis("热度", reversed_data['热度'].tolist(),
                   label_opts=opts.LabelOpts(position="right", formatter="{c}"))
        .reversal_axis()  # 转换为水平条形图
        .set_global_opts(
            title_opts=opts.TitleOpts(title=f"{year}年热度Top10电视剧"),
            xaxis_opts=opts.AxisOpts(name="热度"),
            yaxis_opts=opts.AxisOpts(name="电视剧名称"),
        )
    )

    return bar

# 评分排名条形图
def create_rating_top20_bar(year):
    data_year = data[data['年份'] == year]
    if data_year.empty:
        raise ValueError(f"数据中无 {year} 年的记录，请检查年份输入或数据文件")
    top20_rating = data_year.sort_values('评分', ascending=False).head(20)
    
    bar = (
        Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK, width="600px", height="400px"))
        .add_xaxis(top20_rating['剧名'].tolist())
        .add_yaxis(
            "评分", 
            top20_rating['评分'].tolist(),
            itemstyle_opts=opts.ItemStyleOpts(color="#12cb9a")  # 设置颜色
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title=f"{year}年电视剧评分Top20",
                title_textstyle_opts=opts.TextStyleOpts(color="#fff")  # 设置标题颜色为白色
            ),
            xaxis_opts=opts.AxisOpts(
                name="剧名",
                axislabel_opts=opts.LabelOpts(rotate=45)
            ),
            yaxis_opts=opts.AxisOpts(
                name="评分",
                min_=8,
                max_=10,
                interval=0.1
            ),
            datazoom_opts=opts.DataZoomOpts(type_="inside"),
            legend_opts=opts.LegendOpts()
        )
        .set_series_opts(
            label_opts=opts.LabelOpts(is_show=False)  # 显示评分标签
        )
    )

    return bar

#气泡图
def create_scatter_chart(year):
    scatter_data = []
    for _, row in data.iterrows():
        try:
            if int(row['年份']) == year:
                rating = float(row['评分'])
                if 5 <= rating <= 10:
                    comments = str(row['评论数']).replace(',', '')
                    comments = float(comments) if comments.replace('.', '', 1).isdigit() else 0
                    popularity = int(row['热度'])
                    scatter_data.append({
                        "value": [rating, popularity, comments],
                        "name": row['剧名']
                    })
        except (ValueError, TypeError):
            continue

    scatter = (
        Scatter(init_opts=opts.InitOpts(
            width="800px",  
            height="400px",  
            theme=ThemeType.DARK  
        ))
        .add_xaxis(xaxis_data=[])
        .add_yaxis(
            series_name=f"{year}年电视剧",
            y_axis=scatter_data,
            symbol_size=20,
            label_opts=opts.LabelOpts(is_show=False),
            itemstyle_opts=opts.ItemStyleOpts(color="#7CFC00"),  # 气泡颜色设置为 #7CFC00
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(
                title=f"{year}年电视剧评分-热度-评论数关系",
                subtitle="                                       气泡大小表示评论数量", 
                title_textstyle_opts=opts.TextStyleOpts(
                    color="#fff",  
                    font_size=20
                ),
                subtitle_textstyle_opts=opts.TextStyleOpts(
                    color="#04d4f4", 
                    font_size=14
                )
            ),
            xaxis_opts=opts.AxisOpts(
                name="评分",
                type_="value",
                min_=5,
                max_=10,
                name_location="end",
                
                axislabel_opts=opts.LabelOpts(
                    formatter="{value} 分",
                ),
                interval=0.5,
                splitline_opts=opts.SplitLineOpts(
                    is_show=True,
                    linestyle_opts=opts.LineStyleOpts(color="#AFEEEE")  # X轴网格颜色设置为 #AFEEEE
                )
            ),
            yaxis_opts=opts.AxisOpts(
                name="热度",
                type_="value",
                name_location="end",
                axislabel_opts=opts.LabelOpts(
                ),
                splitline_opts=opts.SplitLineOpts(
                    is_show=True,
                    linestyle_opts=opts.LineStyleOpts(color="#AFEEEE")  # Y轴网格颜色设置为 #AFEEEE
                )
            ),
            tooltip_opts=opts.TooltipOpts(
                trigger="item",
                formatter=JsCode("function(params){return params.data.name;}"),
            ),
            visualmap_opts=opts.VisualMapOpts(
                type_="size",
                min_=0,
                max_=max(d["value"][2] for d in scatter_data) if scatter_data else 1000000,
                dimension=2,
                orient="vertical",
                pos_right="10",
                pos_top="center",
                range_size=[10, 50],
            ),
        )
    )

    return scatter



# 创建 Flask 应用实例
app = Flask(__name__)

# 定义根路由
@app.route('/')
def index():
    return render_template('index.html')

# 定义 new.html 路由
@app.route('/new.html')
def new():
    return render_template('new.html')

# 定义饼图路由
@app.route('/pie_chart/<int:year>')
def pie_chart(year):
    try:
        c = generate_pie_chart(year)
        return c.render_embed()
    except ValueError as e:
        return str(e)


# 定义热度Top10水平条形图路由
@app.route('/top10_hot_bar/<int:year>')
def top10_hot_bar(year):
    try:
        c = create_top10_hot_bar(year)
        return c.render_embed()
    except ValueError as e:
        return str(e)

# 定义评分排名条形图路由
@app.route('/rating_top20_bar/<int:year>')
def rating_top20_bar(year):
    try:
        c = create_rating_top20_bar(year)
        return c.render_embed()
    except ValueError as e:
        return str(e)

# 定义气泡图路由
@app.route('/scatter_chart/<int:year>')
def scatter_chart(year):
    try:
        c = create_scatter_chart(year)
        return c.render_embed()
    except ValueError as e:
        return str(e)


@app.route('/line_chart.html')
def line_chart():
    return render_template('line_chart.html')

@app.route('/type_rating_bar')
def type_rating_bar():
    return render_template('type_rating_bar.html')

@app.route('/rose_chart')
def rose_chart():
    return render_template('rose_chart.html')

@app.route('/wordcloud')
def wordcloud():
    return render_template('wordcloud.html')





if __name__ == '__main__':
    app.run(debug=True)